﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


/* 
 * This class is responsible for positioning the graphics.
 * It is a variable used in the Sprite class
 */
namespace Pulse
{
    class Animation : ICloneable
    {
        #region Variables
        // Specifies how each frame is laid out on a sprite sheet
        public enum AnimFrameType
        {
            GridFrames,
            IndividualFrames
        }
        // Though set to empty, Destination should be changed by other classes 
        private Rectangle Source = Rectangle.Empty;
        private Rectangle[] Sources;
        public int spriteMapWidth = 1;
        public int currentFrame { get; set; }
        public int frameCount { get; set; }
        public float frameTime = 0.0f;
        public string nextAnimation { get; set; }

        public float elapsedTime = 0.0f;
        public bool Looping = true;
        public bool Active = true;
        public AnimFrameType frameType; 
        #endregion

        #region Constructors
        public Animation(Rectangle source, int framecount, int mapWidth)
        {
            this.Source = source;
            this.frameCount = framecount;
            this.spriteMapWidth = mapWidth;
            this.frameType = AnimFrameType.GridFrames;
        }

        public Animation(int x, int y, int fWidth, int fHeight, int framecount, int mapWidth, float frametime)
        {
            this.Source = new Rectangle(x, y, fWidth, fHeight);
            this.frameCount = framecount;
            this.spriteMapWidth = mapWidth;
            this.frameTime = frametime;
            this.frameType = AnimFrameType.GridFrames;
        }

        public Animation(int x, int y, int fWidth, int fHeight, int framecount, int mapWidth, float frametime,
            string nextAnim)
        {
            this.Source = new Rectangle(x, y, fWidth, fHeight);
            this.frameCount = framecount;
            this.spriteMapWidth = mapWidth;
            this.frameTime = frametime;
            this.nextAnimation = nextAnim;
            this.frameType = AnimFrameType.GridFrames;
        }

        public Animation(Rectangle[] sources, float frametime)
        {
            this.frameCount = sources.Count();
            this.frameTime = frametime;
            this.Sources = new Rectangle[frameCount];
            this.frameType = AnimFrameType.IndividualFrames;

            for (int index = 0; index < frameCount; index++)
                this.Sources[index] = sources[index];
        }
        #endregion

        public float getFrameTime
        {
            get { return frameTime; }
            set { frameTime = value; }
        }

        public Rectangle getCurrentSourceRectangle
        {
            get 
            {
                Rectangle temp = Rectangle.Empty;
                switch (frameType)
                {
                    case AnimFrameType.GridFrames:
                        temp = getCurrentGridFrame(currentFrame);
                        break;
                    case AnimFrameType.IndividualFrames:
                        temp = getCurrentIndividualFrame(currentFrame);
                        break;
                }
                return temp;
            }       
        }

        public Rectangle getCurrentGridFrame(int frameIndex)
        {
            int lengthX = Source.X + (Source.Width * frameIndex);
            int x = lengthX % spriteMapWidth;
            int y = lengthX / spriteMapWidth;

            return new Rectangle(x,
                Source.Y + (y * Source.Height),
                Source.Width,
                Source.Height);
        }

        public Rectangle getCurrentIndividualFrame(int frameIndex)
        {
            return Sources[frameIndex];
        }

        public void Update(GameTime gametime)
        {
            //if (!Active) { return; }

            elapsedTime += (float)gametime.ElapsedGameTime.TotalSeconds;

            /* this section of code is for playing frames sequentially */

            // Used for animating sprites by playing different frames sequentially
            if (elapsedTime > frameTime)
            {
                elapsedTime = 0.0f;
                // Move to the next frame
                currentFrame = (currentFrame + 1) % frameCount;
            }

        }

        public object Clone()
        {
            if (frameType == AnimFrameType.GridFrames)
                return new Animation(this.Source.X, this.Source.Y,
                    this.Source.Width, this.Source.Height,
                    this.frameCount, this.spriteMapWidth, this.frameTime, this.nextAnimation);
            else if (frameType == AnimFrameType.IndividualFrames)
                return new Animation(this.Sources, this.frameTime);
            else
                return null;
        }
    }


}
